//
//  NSObject+Property.m
//  homework
//
//  Created by Zhao Pengwei on 14-1-16.
//  Copyright (c) 2014年 Baidu. All rights reserved.
//


/*
 case _C_CHR: // char
 case _C_UCHR: // unsigned char
 case _C_SHT: // short
 case _C_USHT: // unsigned short
 case _C_INT: // int
 case _C_UINT: // unsigned int
 case _C_LNG: // long
 case _C_ULNG: // unsigned long
 case _C_LNG_LNG: // long long
 case _C_ULNG_LNG: // unsigned long long
 case _C_FLT: // float
 case _C_DBL: // double
 return [NSNumber class];
 
 case _C_BOOL: // C++ bool or C99 _Bool
 return objc_getClass("NSCFBoolean")
 ?: objc_getClass("__NSCFBoolean")
 ?: [NSNumber class];
 
 case _C_STRUCT_B: // struct
 case _C_BFLD: // bitfield
 case _C_UNION_B: // union
 return [NSValue class];
 
 case _C_ARY_B: // c array
 case _C_PTR: // pointer
 case _C_VOID: // void
 case _C_CHARPTR: // char *
 case _C_CLASS: // Class
 case _C_SEL: // selector
 case _C_UNDEF: // unknown type (function pointer, etc)
 */
#import "NSObject+Property.h"
#import <CoreFoundation/CoreFoundation.h>
#import <objc/runtime.h>
#import <UIKit/UIKit.h>

@implementation NSObject (Property)

+ (void)object:(id)object setValue:(id)value forKey:(NSString *)key
{
    if ([key length] > 0) {
        NSString *firstText = [key substringToIndex:1];
        NSString *otherText = [key substringFromIndex:1];
        firstText = [firstText uppercaseString];
        NSString *selectorString = [NSString stringWithFormat:@"set%@%@:",firstText,otherText];
        if ([object respondsToSelector:NSSelectorFromString(selectorString)]) {
            [object setValue:value forKey:key];
        }
    }
}

static BOOL IsNumberType(char first) {
	return (first == _C_INT || first == _C_UINT || first == _C_FLT || first == _C_DBL
	        || first == _C_CHR ||  first == _C_UCHR || first == _C_BOOL ||
	        first == _C_LNG_LNG || first == _C_ULNG_LNG  ||
	        first == _C_LNG || first == _C_ULNG || first == _C_SHT || first == _C_USHT);
}

+ (void)setupObject:(id)obj1 withObject:(id)obj2 {
	[self setupObject:obj1 withObject:obj2 changeValueToObject:NO];
}

+ (id)valueWithProperty:(objc_property_t)propert {
	uint attributesCount = 0;
	objc_property_attribute_t *attributes = property_copyAttributeList(propert, &attributesCount);

	for (int i = 0; i < attributesCount; i++) {
		switch (attributes[i].name[0]) {
			case 'T':
				break;

			case 'C':
				break;

			case '&':
				break;

			case 'G':     // Getter
				break;

			case 'S':     // Setter
				break;

			case 'D':     // is dynamic property?
				break;

			default:
				break;
		}
	}
	free(attributes);
	return nil;
}

//+ (NSNumber *)changeValue:(id)value fortype:(NSString *)type {
//	if ([type isEqualToString:@"c"]) {
//		return [NSNumber numberWithChar:value];
//	}
//	if ([type isEqualToString:@"C"]) {
//		return [NSNumber numberWithUnsignedChar:value];
//	}
//	if ([type isEqualToString:@"d"]) {
//		return [NSNumber numberWithDouble:value];
//	}
//	if ([type isEqualToString:@"i"]) {
//		return [NSNumber numberWithInteger:value];
//	}
//	if ([type isEqualToString:@"I"]) {
//		return [NSNumber numberWithUnsignedInt:value];
//	}
//	if ([type isEqualToString:@"l"]) {
//		return [NSNumber numberWithLong:value];
//	}
//	if ([type isEqualToString:@"L"]) {
//		return [NSNumber numberWithUnsignedLong:value];
//	}
//	if ([type isEqualToString:@"s"]) {
//		return [NSNumber numberWithShort:value];
//	}
//	if ([type isEqualToString:@"S"]) {
//		return [NSNumber numberWithUnsignedShort:value];
//	}
//
//	if ([type isEqualToString:@"q"]) {
//		return [NSNumber numberWithLongLong:value];
//	}
//	if ([type isEqualToString:@"Q"]) {
//		return [NSNumber numberWithUnsignedLongLong:value];
//	}
//	if ([type isEqualToString:@"f"]) {
//		return [NSNumber numberWithFloat:value];
//	}
//	return value;
//}

+ (void)setupObject:(id)obj1 withObject:(id)obj2 changeValueToObject:(BOOL)change {
	Class superClass = [obj1 class];
	while (superClass != NULL &&
	       ![NSStringFromClass(superClass) isEqualToString:@"NSObject"]) {
		u_int32_t count;

		objc_property_t *properties = class_copyPropertyList([superClass class], &count);


		for (int i = 0; i < count; i++) {
			objc_property_t propert = properties[i];
			NSString *name = [[NSString alloc] initWithCString:property_getName(propert) encoding:NSUTF8StringEncoding];

			if ([name length] <= 0) {
				continue;
			}

			// obj2 拥有key这个propert赋值
			if ([obj2 respondsToSelector:NSSelectorFromString(name)]) {
				id value = [obj2 valueForKey:name];
				if (value == NSNull.null) {
					continue;
				}

				char *type2Value = property_copyAttributeValue(propert, "T");
				char *type1Value = property_copyAttributeValue(class_getProperty([obj1 class], [name cStringUsingEncoding:NSUTF8StringEncoding]), "T");
				char type2Value_type = type2Value[0];
				char type1Value_type = type1Value[0];
				if (IsNumberType(type1Value_type) && IsNumberType(type2Value_type)) {
					[NSObject object:obj1 setValue:value forKey:name];
				}
				else {
					NSString *type2 = [[NSString alloc] initWithCString:type2Value encoding:NSUTF8StringEncoding];
					NSString *type1 = [[NSString alloc] initWithCString:type1Value encoding:NSUTF8StringEncoding];

#pragma mark ============= TODOP 待优化 attributes[i].name[0] =============

					//                if (change) {
					//                    [self valueWithProperty:propert];
					//                    value = [self changeValue:value fortype:type1];
					//                }

					if ([type1 isEqualToString:type2]) {
                        if (value) {
                            [NSObject object:obj1 setValue:value forKey:name];
                        }
					}
				}
				free(type1Value);
				free(type2Value);
			}
		}
		superClass = [superClass superclass];
		free(properties);
	}
}

+ (void)setupObject:(id)model fromPBObject:(id)pb
{
    Class modelClass = [model class];
//    Class pbClass = [model class];
    while (modelClass != NULL &&
           ![NSStringFromClass(modelClass) isEqualToString:@"PBGeneratedMessage"]) {
        u_int32_t count;
        
        objc_property_t *properties = class_copyPropertyList([modelClass class], &count);
        
        
        for (int i = 0; i < count; i++) {
            objc_property_t propert = properties[i];
//            char *modelPropertType = property_copyAttributeValue(propert, "T");
            
            NSString *name = [[NSString alloc] initWithCString:property_getName(propert) encoding:NSUTF8StringEncoding];
            
            if ([name length] <= 0) {
                continue;
            }
            
            // obj2 拥有key这个propert赋值
            if ([pb respondsToSelector:NSSelectorFromString(name)])
            {
                id value = [pb valueForKey:name];
                
                if ([NSStringFromClass([value class]) isEqualToString:@"PBGeneratedMessage"])
                {
                    
                }
                else
                {
                    
                }
            }
        }
        modelClass = [modelClass superclass];
        free(properties);
    }
}

- (id)refactorPBToClass:(Class)aClass
{
    id obj = [[aClass alloc] init];
    [NSObject setupObject:obj fromPBObject:self];
    return obj;
}

- (id)refactorObjectToClass:(Class)aClass {
	return [self refactorObjectToClass:aClass changeValueToObject:NO];
}

- (id)refactorObjectToClass:(Class)aClass changeValueToObject:(BOOL)change {
	id obj = [[aClass alloc] init];
	[NSObject setupObject:obj withObject:self changeValueToObject:change];
	return obj;
}

- (id)refactorObjectToClassAndChangeValueToObject:(Class)aClass {
	return [self refactorObjectToClass:aClass changeValueToObject:YES];
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return NO;
}
@end
